package jp.ac.u_tokyo.dch.core.db;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

import jp.ac.u_tokyo.dch.core.exceptions.DBException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Connection ラッパークラス
 *
 * @version 1.1
 */
public class DBConnection  {

	/** ロガー */
	private static Log logger = LogFactory.getLog(DBConnection.class);

	/** Connection */
	private Connection con = null;

	/**
	 * コンストラクタ
	 * @param con Connection
	 */
	public DBConnection(Connection con) {
		this.con = con;
	}


	public void clearWarnings() throws DBException {

		try {
			con.clearWarnings();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}

	}

	public void close() throws DBException {
		logger.info("DB CONNECTION [ Close ] HashCode :[" + String.valueOf(con.hashCode()) + "]");
		try {
			con.close();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}

	}

	public void commit() throws DBException {
		logger.info("DB CONNECTION [ Commit ] HashCode :[" + String.valueOf(con.hashCode()) + "]");
		try {
			con.commit();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}

	}

	public CustomStatement createStatement() throws DBException {

		try {
			Statement stmt = con.createStatement();
			return new CustomStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomStatement createStatement(int resultSetType, int resultSetConcurrency)
			throws DBException {

		try {
			Statement stmt = con.createStatement(resultSetType, resultSetConcurrency);
			return new CustomStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomStatement createStatement(int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws DBException {
		try {
			Statement stmt = con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
			return new CustomStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public boolean getAutoCommit() throws DBException {

		try {
			return con.getAutoCommit();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public String getCatalog() throws DBException {
		try {
			return con.getCatalog();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public int getHoldability() throws DBException {

		try {
			return con.getHoldability();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public DatabaseMetaData getMetaData() throws DBException {

		try {
			return con.getMetaData();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public int getTransactionIsolation() throws DBException {

		try {
			return con.getTransactionIsolation();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public Map<String, Class<?>> getTypeMap() throws DBException {

		try {
			return con.getTypeMap();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public SQLWarning getWarnings() throws DBException {

		try {
			return con.getWarnings();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public boolean isClosed() throws DBException {

		try {
			return con.isClosed();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public boolean isReadOnly() throws DBException {

		try {
			return con.isReadOnly();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public String nativeSQL(String sql) throws DBException {

		try {
			return con.nativeSQL(sql);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomCallableStatement prepareCall(String sql) throws DBException {

		try {
			CallableStatement stmt = con.prepareCall(sql);
			return new CustomCallableStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomCallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency) throws DBException {

		try {
			CallableStatement stmt = con.prepareCall(sql, resultSetType, resultSetConcurrency);
			return new CustomCallableStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomCallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws DBException {

		try {
			CallableStatement stmt = con.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
			return new CustomCallableStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql) throws DBException {

		try {
			PreparedStatement stmt = con.prepareStatement(sql);;
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
			throws DBException {

		try {

			PreparedStatement stmt = con.prepareStatement(sql, autoGeneratedKeys);
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);

		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql, int[] columnIndexes)
			throws DBException {

		try {

			PreparedStatement stmt = con.prepareStatement(sql, columnIndexes);
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);

		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql, String[] columnNames)
			throws DBException {

		try {
			PreparedStatement stmt =  con.prepareStatement(sql, columnNames);
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency) throws DBException {

		try {
			PreparedStatement stmt =  con.prepareStatement(sql, resultSetType, resultSetConcurrency);
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public CustomPreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws DBException {

		try {
			PreparedStatement stmt =   con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
			logger.info("PreparedStatement [ Open ] HashCode :[" + String.valueOf(stmt.hashCode()) + "]");
			return new CustomPreparedStatement(stmt);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void releaseSavepoint(Savepoint savepoint) throws DBException {

		try {
			con.releaseSavepoint(savepoint);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void rollback() throws DBException {

		logger.info("DB CONNECTION [ Rollback ] HashCode :[" + String.valueOf(con.hashCode()) + "]");

		try {
			con.rollback();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void rollback(Savepoint savepoint) throws DBException {

		try {

			logger.info("DB CONNECTION [ Rollback ] HashCode :[" + String.valueOf(con.hashCode()) + "] savepoint:[" + savepoint.getSavepointName() + "]");
			con.rollback(savepoint);

		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setAutoCommit(boolean autoCommit) throws DBException {

		try {
			con.setAutoCommit(autoCommit);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setCatalog(String catalog) throws DBException {

		try {
			con.setCatalog(catalog);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setHoldability(int holdability) throws DBException {

		try {
			con.setHoldability(holdability);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setReadOnly(boolean readOnly) throws DBException {

		try {
			con.setReadOnly(readOnly);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public Savepoint setSavepoint() throws DBException {

		try {
			return con.setSavepoint();
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public Savepoint setSavepoint(String name) throws DBException {

		try {
			return con.setSavepoint(name);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setTransactionIsolation(int level) throws DBException {

		try {
			con.setTransactionIsolation(level);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

	public void setTypeMap(Map<String, Class<?>> map) throws DBException {

		try {
			con.setTypeMap(map);
		} catch ( SQLException e ) {
			logger.error("ERROR",e);
			throw new DBException();
		}
	}

}
